#ifdef _WIN32
#include <WinSock2.h>
#endif

//types
#define INT		int
#define WORD	unsigned short int
#define DWORD	unsigned int
#define CHAR	char
#define BYTE	unsigned char

#include <list>
#include <string>
#include <iostream>

class TCPMan;
class TCPConnection;
class TCPServer;

class TCPMan
{
	friend TCPConnection;
	friend TCPServer;
public:
	TCPMan();
	~TCPMan();
	TCPConnection *Connect(const char *szAddr, WORD wPort);
	TCPServer *CreateServer(WORD wPort);

	void DeleteClient(TCPConnection *pClient);
	void DeleteServer(TCPServer *pServer);

	void Update(DWORD dwMilliSecs);		
	bool IsWork();


protected:
	virtual void				OnError(int iError, const char *szDescription);
	std::list<TCPConnection*>	m_pConnections;
	std::list<TCPServer*>		m_pServers;
	bool						m_fIsWork;
	bool						TryUp();
	void						TryDown();
};

class TCPConnection
{
	friend TCPMan;
public:
	TCPConnection(const char *szAddress, WORD wPort, TCPMan *pManager);
	~TCPConnection();

	int Send(const char *szMessage, DWORD dwSize);
	void Update(DWORD dwMilliSecs);
	bool IsConnect();

protected:
	bool TryToConnect();
	bool TryToDisconnect();
	bool TryToReceive();

	virtual void OnReceive(TCPConnection *pThis, const char *pData, 
		WORD wSize);
	virtual void OnConnect();
	virtual void OnDisconnect();
	virtual void OnError(long lError, const char *szErrorDesc);

	std::string	m_sAddress;
	WORD		m_wPort;
	TCPMan		*m_pManager;
	std::list<BYTE*>	m_Messages;

private:
	SOCKET		m_Socket;
	bool		m_SafeSocket();	//Create TCP/IP socket. If
	bool		m_SafeBind();
	bool		m_SafeConnect();
	unsigned long	m_GetBufferLength();
	void		m_SafeSend();
	void		m_SafeRecv();


	bool		m_fIsSocked;		//Did sock successfull?
	bool		m_fIsBinded;		//Did bind successfull?
	bool		m_fIsConnected;		//Did connect successfull?
	
};

class TCPServer
{
	friend TCPMan;
public:
	TCPServer(WORD wPort);
	~TCPServer();

	void Update(WORD wMilliSecs);
	void Send(TCPConnection *pReceiver);	
protected:
	void Down(){;};
	void TryUp(){;};

	virtual void OnAccept(TCPServer *pThis, TCPConnection *pClient){;};
	virtual void OnClose(TCPServer *pThis, TCPConnection *pClient){;};
	virtual void OnReceive(TCPServer *pThis, TCPConnection *pSender, 
		const char *pData, DWORD dwDataSize){;};
	virtual void OnError(TCPServer *pThis, DWORD dwError){;};
};